#include "clprs.h"
/*
gst-launch -ve udpsrc uri=udp://192.168.52.128:5566 port=5566  caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96" ! rtpjitterbuffer ! rtph264depay ! h264parse ! mp4mux name=mux udpsrc uri=udp://192.168.52.128:5588 port=5588 caps="application/x-rtp" ! rtppcmudepay  ! mulawdec ! audioconvert ! voaacenc  ! mux. mux. ! filesink location=file.mp4
 */
#define VURL_STR	"udp://192.168.52.128:5566"
#define VPORT		5566
#define VIDEO_CAPS	"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96"
#define AURL_STR	"udp://192.168.52.128:5588"
#define APORT		5588
#define AUDIO_CAPS	"application/x-rtp"
#define DEST_FILE	"./my.mp4"

typedef struct _clprs_server clprs_server;

struct _clprs_server{
	GMainLoop *loop;
	GstElement *pipeline;

	GstElement *vudpsrc;
	GstElement *vrtpjitterbuffer;
	GstElement *rtph264depay;
	GstElement *h264parse;

	GstElement *audpsrc;
	GstElement *artpjitterbuffer;
	GstElement *rtppcmudepay;
	GstElement *mulawdec;
	GstElement *audioconvert; 
	GstElement *voaacenc;

	GstElement *mp4mux;
	GstElement *filesink;
	
};

clprs_server g_server;

static gboolean clprs_set_src(GstElement *udpsrc, clprs_uri_t *uri) 
{
	GstCaps *caps;

	g_assert(udpsrc);
	if(!uri){
		g_error("No uri presented!");
		return FALSE;
	}

	g_object_set (G_OBJECT (udpsrc), "uri", uri->uri_str, NULL);
	g_object_set (G_OBJECT (udpsrc), "port", uri->port, NULL);
	caps = gst_caps_from_string(uri->caps);
	g_object_set(udpsrc, "caps", caps, NULL);
	gst_caps_unref (caps);

	return TRUE;
}

static void clprs_send_eos(GstElement *element)
{
	GstEvent *event;

	event = gst_event_new_eos();
	gst_element_send_event(element, event);
}

static gboolean bus_message(GstBus * bus, GstMessage * message, clprs_server *server)
{
	GST_DEBUG("######## LIDE: Got message %s", gst_message_type_get_name (GST_MESSAGE_TYPE (message)));

	switch (GST_MESSAGE_TYPE (message)) {
		case GST_MESSAGE_ERROR:
			{
				GError *err;
				gchar *debug;

				gst_message_parse_error (message, &err, &debug);
				g_print ("Error: %s\n", err->message);
				g_error_free (err);
				g_free (debug);
				g_main_loop_quit (server->loop);
				break;
			}
		case GST_MESSAGE_EOS:
			{
				/* end-of-stream */
				g_print("\nQuit main loop ......\n");
	//			g_usleep (5 * G_USEC_PER_SEC);
				g_main_loop_quit (server->loop);
				break;
			}
		default:
			break;
	}

	return TRUE;
}

static void on_pad_added(GstElement *element, GstPad *pad,	gpointer data)
{
	GstPadTemplate *mux_template = NULL;
	GstPad *sinkpad;
	GstElement *mp4mux = (GstElement *)data;

	/* We can now link this pad with the vorbis-decoder sink pad */
	g_print("Dynamic pad created, linking demuxer/decoder\n");

	gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(mp4mux), "video_%u");
	sinkpad = gst_element_request_pad (mp4mux, mux_template, NULL, NULL);//= gst_element_get_static_pad(mp4mux, "sink");

	gst_pad_link (pad, sinkpad);

	gst_object_unref (sinkpad);
}

static void on_pad_added1(GstElement *element, GstPad *pad,	gpointer data)
{
	GstPadTemplate *mux_template = NULL;
	GstPad *sinkpad;
	GstElement *mp4mux = (GstElement *) data;

	/* We can now link this pad with the vorbis-decoder sink pad */
	g_print ("Dynamic pad created, linking demuxer/decoder\n");

	gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(mp4mux), "audio_%u");
	sinkpad = gst_element_request_pad (mp4mux, mux_template, NULL, NULL);//= gst_element_get_static_pad(mp4mux, "sink");

	gst_pad_link (pad, sinkpad);

	gst_object_unref (sinkpad);
}

int main (int argc, char *argv[]) 
{
	gboolean link_ok;
	clprs_uri_t *uri;
	GstBus *bus;
	guint bus_watch_id;
	clprs_server *server = &g_server;

	gst_init(&argc, &argv);
	server->loop = g_main_loop_new(NULL, FALSE);//create main loop
	
	uri = (clprs_uri_t*)g_malloc(sizeof(clprs_uri_t));
	uri->uri_str = g_strdup(VURL_STR);
	uri->port = VPORT;
	strcpy(uri->caps, VIDEO_CAPS);

	/* create a new pipeline */
	server->pipeline = gst_pipeline_new("pipeline");
	server->vudpsrc = gst_element_factory_make("udpsrc", "vrtpsrc");

	/* get date from uri=udp://192.168.186.128:5555 port=5555 */
	if(!clprs_set_src(server->vudpsrc, uri)){
		g_error("Set uri err!!");
	}
	/* create elements */
	server->vrtpjitterbuffer = gst_element_factory_make("rtpjitterbuffer", "vjitterbuffer");
	server->rtph264depay = gst_element_factory_make("rtph264depay", "h264depay");
	server->h264parse = gst_element_factory_make("h264parse", "h264parse");
 
	server->audpsrc = gst_element_factory_make("udpsrc", "artpsrc");
	uri->uri_str = g_strdup(AURL_STR);
	uri->port = APORT;
	strcpy(uri->caps, AUDIO_CAPS);
	if(!clprs_set_src(server->audpsrc, uri)){
		g_error("Set uri err!!");
	}
	server->artpjitterbuffer = gst_element_factory_make("rtpjitterbuffer", "ajitterbuffer");
	server->rtppcmudepay = gst_element_factory_make("rtppcmudepay", "rtppcmudepay");
	server->mulawdec = gst_element_factory_make("mulawdec", "mulawdec");
	server->audioconvert = gst_element_factory_make("audioconvert", "audioconvert");
	server->voaacenc = gst_element_factory_make("voaacenc", "voaacenc");

	server->mp4mux = gst_element_factory_make("mp4mux", "mp4mux");
//	g_object_set(G_OBJECT (server->mp4mux), "fragment-duration", 10, NULL);
	server->filesink = gst_element_factory_make("filesink", "sink");
	g_object_set(G_OBJECT (server->filesink), "location", DEST_FILE, NULL);
	//g_object_set (G_OBJECT (server->filesink), "sync", TRUE, NULL);

	/* add elements to pipeline */
	gst_bin_add_many(GST_BIN (server->pipeline), server->vudpsrc, server->vrtpjitterbuffer, server->rtph264depay, server->h264parse, NULL);
	gst_bin_add_many(GST_BIN (server->pipeline), server->audpsrc,  server->artpjitterbuffer, server->rtppcmudepay, server->mulawdec, server->audioconvert, server->voaacenc, NULL);
	gst_bin_add_many(GST_BIN (server->pipeline), server->mp4mux, server->filesink, NULL);
	/* link elements */
	if(!gst_element_link_many(server->vudpsrc, server->vrtpjitterbuffer, server->rtph264depay, server->h264parse, server->mp4mux, server->filesink, NULL)){
		g_error("1 Elements link error!");
	}
	if(!gst_element_link_many(server->audpsrc,  server->artpjitterbuffer, server->rtppcmudepay, server->mulawdec, server->audioconvert, server->voaacenc, server->mp4mux, NULL)){
		g_error("2 Elements link error!");
	}
//	if(!gst_element_link(server->mp4mux, server->filesink)){
//		g_error("3 Elements link error!");
//	}
//	g_signal_connect(server->h264parse, "pad-added", G_CALLBACK(on_pad_added), server->mp4mux);
//	g_signal_connect(server->voaacenc, "pad-added", G_CALLBACK(on_pad_added1), server->mp4mux);

	/*
	if(!gst_element_link(server->h264parse, server->mp4mux)){
		g_error("4 Elements link error!");
	}
	if(!gst_element_link(server->audioconvert, server->mp4mux)){
		g_error("5 Elements link error!");
	}
*/
	bus = gst_pipeline_get_bus(GST_PIPELINE(server->pipeline));


	bus_watch_id = gst_bus_add_watch(bus, (GstBusFunc)bus_message, server);
	gst_object_unref (bus);

	g_timeout_add(1000 * 60 * 5, (GSourceFunc)clprs_send_eos, server->pipeline);

	/* play */
	gst_element_set_state(server->pipeline, GST_STATE_PLAYING);
	/* main loop */
	g_print("\nStart main loop ......\n");
	g_main_loop_run(server->loop);
	/* stop pipeline */
	gst_element_set_state(server->pipeline, GST_STATE_NULL);
	/* free src */
	g_free(uri->uri_str);
	gst_object_unref(GST_OBJECT(server->pipeline));
	g_source_remove(bus_watch_id);
	g_main_loop_unref(server->loop);
	exit (0);
}
